package com.zlk.learning.bytebuddy;

import com.alibaba.fastjson.JSONObject;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;

import static sun.tools.java.RuntimeConstants.ACC_PRIVATE;
import static sun.tools.java.RuntimeConstants.ACC_VOLATILE;

/**
 * @author zhoulk@fiture.com
 * @date 2021/9/8
 */
public class TestClasOutput {

    public static void main(String[] args) throws Exception {
        DynamicType.Builder<?> dynamicBuilder = new ByteBuddy()
                .subclass(Object.class)
                .defineField("proxyContext1", Object.class, ACC_PRIVATE | ACC_VOLATILE)
                .implement(EnhancedInterface.class)
                .intercept(FieldAccessor.ofField("proxyContext1"));

        outputClazz("customClazz", dynamicBuilder.make()
                .load(Example001.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                .getBytes());

        outputInterceptClass();

    }


    private static void outputInterceptClass() throws InstantiationException, IllegalAccessException {

        outputClazz("interceptionBytebuddy", new ByteBuddy()
                .subclass(Dog.class)
                .method(ElementMatchers.named("hello"))
                .intercept(MethodDelegation.to(MyServiceInterceptor.class))
                .make()
                .load(Example002.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER).getBytes());

    }

    private static void outputClazz(String name, byte[] bytes) {
        FileOutputStream out = null;
        try {
            String pathName = TestClasOutput.class.getResource("/").getPath() + name + ".class";
            out = new FileOutputStream(new File(pathName));
            System.out.println("类输出路径：" + pathName);
            out.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != out) try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
